﻿using System.Collections.Concurrent;

using PipeClient.Model;
using PipeClient.SystemAllot;

using RpcHelper;
using RpcHelper.Config;
namespace PipeClient.Config
{
    public class PipeConfig
    {

        private static int _SyncTimeOut = LocalConfig.Local.GetValue("pipe:Client:SyncTimeOut", 12000);

        private static Interface.ISocketEvent _SocketEvent = null;


        public static Interface.ISocketEvent SocketEvent
        {
            get => PipeConfig._SocketEvent;
            set => PipeConfig._SocketEvent = value;
        }

        private static Interface.IAllot _Allot = new ReplyAllot();

        /// <summary>
        /// 用于接收服务端的广播
        /// </summary>
        public static Interface.IAllot Allot
        {
            get => (Interface.IAllot)PipeConfig._Allot.Clone();
            set => PipeConfig._Allot = value;
        }

        /// <summary>
        /// 服务器名
        /// </summary>
        private static string _ServerName = LocalConfig.Local.GetValue("pipe:Client:ServerName", ".");

        /// <summary>
        /// 服务器名
        /// </summary>
        public static string ServerName
        {
            get => PipeConfig._ServerName;
            set => PipeConfig._ServerName = value;
        }


        /// <summary>
        /// 隧道名称
        /// </summary>
        private static string _PipeName = LocalConfig.Local.GetValue("pipe:Client:PipeName");

        /// <summary>
        /// 隧道名称
        /// </summary>
        public static string PipeName
        {
            get => PipeConfig._PipeName;
            set => PipeConfig._PipeName = value;
        }

        private static string _ServerKey = LocalConfig.Local.GetValue("pipe:Client:ServerKey", "6xy3#7a%ad").GetMd5();

        /// <summary>
        /// 服务端密钥
        /// </summary>
        public static string ServerKey
        {
            get => PipeConfig._ServerKey;
            set => PipeConfig._ServerKey = Tools.GetMD5(value);
        }
        /// <summary>
        /// 同步等待时间(毫秒)
        /// </summary>
        public static int SpinWait
        {
            get;
        } = LocalConfig.Local.GetValue<ushort>("pipe:Client:SpinWait", 50);
        private static readonly ConcurrentDictionary<string, ServerConConfig> _ServerConnectArg = new ConcurrentDictionary<string, ServerConConfig>();

        public void SetConArg(string host, string pipeName, string publicKey, params string[] arg)
        {
            AddConArg(host, pipeName, publicKey, arg);
        }
        public void SetConArg(string host, string pipeName, params string[] arg)
        {
            AddConArg(host, pipeName, arg);
        }
        public static void AddConArg(string host, string pipeName, params string[] arg)
        {
            AddConArg(host, pipeName, null, arg);
        }


        public static void AddConArg(string host, string pipeName, string publicKey, params string[] arg)
        {
            if (arg == null)
            {
                arg = System.Array.Empty<string>();
            }
            string key = string.Format("{0}:{1}", host, pipeName);
            publicKey = publicKey == null ? _ServerKey : Tools.GetMD5(publicKey);
            if (_ServerConnectArg.TryGetValue(key, out ServerConConfig config))
            {
                config.Arg = arg;
                config.ConKey = publicKey;
            }
            else
            {
                _ServerConnectArg.TryAdd(key, new ServerConConfig(publicKey, arg));
            }
        }
        internal static ServerConConfig GetConArg(string serverId)
        {
            return _ServerConnectArg.TryGetValue(serverId, out ServerConConfig config) ? config : new ServerConConfig(_ServerKey, null);
        }


        private static int _HeartbeatTime = LocalConfig.Local.GetValue<int>("pipe:Client:Heartbeat", Tools.GetRandom(60000, 110000));

        /// <summary>
        /// 心跳间隔时间
        /// </summary>
        public static int HeartbeatTime
        {
            get => PipeConfig._HeartbeatTime;
            set => PipeConfig._HeartbeatTime = value;
        }
        /// <summary>
        ///发送超时时间(秒)
        /// </summary>
        private static int _Timeout = LocalConfig.Local.GetValue<int>("pipe:Client:TimeOut", 10);

        /// <summary>
        /// 发送超时时间（秒）
        /// </summary>
        public static int Timeout
        {
            get => PipeConfig._Timeout;
            set => PipeConfig._Timeout = value;
        }
        /// <summary>
        /// 连接超时时间
        /// </summary>
        private static int _ConTimeout = LocalConfig.Local.GetValue<int>("pipe:Client:ConTimeout", 5000);
        /// <summary>
        /// 命名管道链接超时
        /// </summary>
        public static int ConTimeout
        {
            get => PipeConfig._ConTimeout;
            set => PipeConfig._ConTimeout = value;
        }
        /// <summary>
        /// 同步超时时间
        /// </summary>
        public static int SyncTimeOut
        {
            get => _SyncTimeOut;

            set => _SyncTimeOut = value;
        }
        /// <summary>
        /// 连接池最小链接数
        /// </summary>
        public static int ClientNum { get; set; } = LocalConfig.Local.GetValue<int>("pipe:Client:ClientNum", 2);
        /// <summary>
        /// 上传文件计算MD5最大大小
        /// </summary>
        public static int UpFileMD5LimitSize { get; set; } = LocalConfig.Local.GetValue<int>("pipe:Client:UpFileMD5LimitSize", 5 * (1024 * 1024));
        /// <summary>
        /// 文件上传发送超时时间
        /// </summary>
        public static int UpFileSendTimeOut { get; set; } = LocalConfig.Local.GetValue<int>("pipe:Client:UpFileSendTimeOut", 10);

    }
}
